// @/utils/TtsPlayer.js

import PCMPlayWorker from './pcm-play.worker-si.js?worker'
class TtsPlayer {
  constructor() {
    this.text = []
    this.worker = new PCMPlayWorker() // Web Worker，用于解码 base64 -> Float32Array
    this.audioCtx = null // Web Audio API 上下文
    this.audioDatas = [] // 存放已解码的音频片段（Float32Array 数组）
    this.audioBuffer = new Float32Array(0)
    this.isPlaying = false // 播放状态标志
    this.source = null // 当前正在播放的（音轨） AudioBufferSourceNode
    this.monitoringConnected = false // 记录是否正在播放（耳机插入状态）

    this.init() // 初始化音频上下文
    this.setupWorkerListener() // 监听 worker 消息
    this.initDeviceChangeListener() // 启动耳机检测
  }

  audioDatasIndex = 0
  async init() {
    this.audioCtx = new (window.AudioContext || window.webkitAudioContext)()
    await this.audioCtx.resume() // 确保上下文处于激活状态（浏览器自动播放策略）
  }
  createSilence(sampleCount) {
    return new Float32Array(sampleCount).fill(0)
  }
  //监听 Worker 消息
  setupWorkerListener() {
    this.worker.onmessage = (e) => {
      const { command, data, textData } = e.data
      if (command === 'newAudioData' && data.length > 0) {
        this.audioDatas.push(data) // 收到解码后的 Float32Array 数据 data 就推进播放队列里

        // this.text.push(textData)
        if (!this.isPlaying) {
          this.maybePlay()
        }
      }
    }
  }

  //根据耳机状态决定是否播放
  maybePlay() {
    if (
      this.monitoringConnected &&
      !this.isPlaying &&
      this.audioDatas.length > 0
    ) {
      this.isPlaying = true
      this.playNext()
    }
  }

  // 耳机插入/拔出检测
  async initDeviceChangeListener() {
    // 首次检查
    await this.checkAndToggleMonitoring()

    // 监听设备变化
    navigator.mediaDevices.addEventListener('devicechange', async () => {
      console.log('🎧 设备变化，正在检查耳机状态...')
      await this.checkAndToggleMonitoring()
    })
  }

  async checkAndToggleMonitoring() {
    try {
      // 刷新
      await this.refreshAudioDevices()

      const usingHeadphones = await this.isUsingHeadphones()

      // console.log('耳机检测结果:', usingHeadphones);

      if (usingHeadphones) {
        this.connectMonitoring()
      } else {
        this.disconnectMonitoring()
      }

      // console.log(
      //     "🎧 默认输出:", defaultOutput?.label || "未知",
      //     "| 耳机状态:", usingHeadphones ? "已插入" : "未插入",
      //     "| 当前播放:", this.isPlaying
      // );
    } catch (err) {
      console.warn('🎧 设备检测失败:', err)
    }
  }

  // 判断耳机
  async isUsingHeadphones() {
    try {
      // 获取当前设备上所有的媒体输入/输出设备列表（如麦克风、扬声器、摄像头等）
      const devices = await navigator.mediaDevices.enumerateDevices()

      // 从所有设备中筛选出音频输出设备（即：声音播放设备，例如扬声器、耳机、蓝牙音箱等）
      const audioOutputs = devices.filter((d) => d.kind === 'audiooutput')
      // console.log('🎧 音频输出设备列表:', audioOutputs)

      // 系统当前正在使用的默认播放设备
      const defaultOutput = audioOutputs.find((d) => d.deviceId === 'default')
      // console.log('🎧 当前默认输出设备:', defaultOutput?.label)


      if (!defaultOutput) return false

      // 如果没有获取到标签，则使用空字符串作为默认值
      const label = (defaultOutput.label || '').toLowerCase().trim()

      // 明确排除 —— 这些一定不是耳机（尤其是外放设备）
      if (
        label.includes('hdmi') || // HDMI 音频输出（如连接显示器、电视、投影仪）
        label.includes('display') || // 显示器内置扬声器（DisplayPort 或 HDMI）
        label.includes('monitor') || // 显示器音频输出
        label.includes('tv') || // 电视作为音频输出设备
        label.includes('digital audio') || // 数字音频输出（如光纤 SPDIF、同轴）
        label.includes('speaker') || // 内置/外置扬声器（笔记本或台式机）
        label.includes('laptop') || // 笔记本内置音频设备（通常为扬声器）
        label.includes('built-in') || // 系统内置音频（macOS 常见，如 "Built-in Output"）
        label.includes('internal') || // 主板集成声卡的默认输出（非耳机口）
        label.includes('main speaker') || // 某些设备明确标记为主扬声器
        label.includes('扬声器') ||  // 某些设备明确标记为主扬声器
        label.includes('Realtek(R) Audio') // 某些设备明确标记为主扬声器
      ) {
        return false
      }

      //  第二步：明确是耳机的设备关键词
      if (
        label.includes('headphone') || // 有线耳机（3.5mm 插孔，常见于台式机/笔记本）
        label.includes('earphone') || // 入耳式耳机（小型有线耳机，与 headphone 类似）
        label.includes('earbud') || // 入耳式耳塞（如 AirPods 标准版、普通蓝牙耳塞）
        label.includes('headset') || // 头戴式耳机（通常带麦克风，用于语音通话）
        label.includes('bluetooth') || // 蓝牙音频设备（包括蓝牙耳机、音箱、耳塞）
        label.includes('2nd output') || // 第二音频输出（某些双声道声卡的耳机通道）
        (label.includes('realtek') && // Realtek 音频驱动（常见于主板）
          label.includes('output') ) // 排除 Realtek 的输入通道（避免误判）
      ) {
        return true
      }

      // 🟡 第三步：常见耳机品牌（辅助判断）
      const headphoneBrands = [
        'jbl', // JBL 蓝牙音箱/耳机
        'sony', // Sony 耳机
        'bose', // Bose 降噪耳机
        'sennheiser', // 森海塞尔专业耳机
        'beats', // Beats 耳机（苹果旗下）
        'anker', // Anker Soundcore 系列
        'logitech', // 罗技耳机（如 G 系列游戏耳机）
        'xiaomi', // 小米蓝牙耳机
        'huawei', // 华为 FreeBuds 系列
        'apple', // Apple 设备（如 AirPods，但通常已由 bluetooth 覆盖）
        'samsung', // 三星 Galaxy Buds
        'audio-technica', // 铁三角耳机
        'akg', // AKG 耳机（现属 Samsung）
        'b&o', // Bang & Olufsen 高端耳机
        'marshall', // Marshall 造型耳机
        'skullcandy', // Skullcandy 运动耳机
        'plantronics', // Plantronics 通讯耳机
        'airpods', // Apple AirPods
      ]

      if (headphoneBrands.some((brand) => label.includes(brand))) {
        return true
      }

      //兜底逻辑 —— label 存在且未被排除，可能是耳机
      return label !== ''
    } catch (err) {
      return false // 不确定时认为没用耳机
    }
  }

  async refreshAudioDevices() {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
      stream.getTracks().forEach((track) => track.stop())
    } catch (err) {
      console.warn('🎧 刷新设备列表失败:', err)
    }
  }

  // 插入耳机：开始播放队列中的语音
  connectMonitoring() {
    if (this.monitoringConnected) {
      return
    }
    this.monitoringConnected = true
    console.log('✅ 耳机已插入，尝试播放')
    this.maybePlay() // 尝试播放
  }

  // 拔出耳机：停止播放
  disconnectMonitoring() {
    if (!this.monitoringConnected) {
      return
    }
    this.monitoringConnected = false
    console.log('🔇 耳机已拔出，停止播放')

    // 停止当前播放
    if (this.source) {
      this.source.stop()
      this.source = null
    }
    this.isPlaying = false
    this.audioDatasIndex = 0
    this.audioDatas = []
  }

  playNext() {
    //没插入耳机不播放
    if (!this.monitoringConnected) {
      return
    }

    if (!this.audioCtx || this.audioCtx.state === 'closed') {
      this.isPlaying = false
      return
    }
    //播放下一个音频片段（递归播放）
    if (this.audioDatas.length == 0) {
      this.isPlaying = false
      return
    }

    let bufferLength = 0
    const dataLength = this.audioDatas.length
    for (let i = this.audioDatasIndex; i < dataLength; i++) {
      bufferLength += this.audioDatas[i].length
    }
    const audioBuffer = this.audioCtx.createBuffer(1, bufferLength, 16000)
    let offset = 0
    const nowBuffering = audioBuffer.getChannelData(0)
    for (let i = this.audioDatasIndex; i < dataLength; i++) {
      const audioData = this.audioDatas[i]
      if (audioBuffer.copyToChannel) {
        audioBuffer.copyToChannel(audioData, 0, offset)
      } else {
        for (let j = 0; j < audioData.length; j++) {
          nowBuffering[offset + j] = audioData[j]
        }
      }
      offset += audioData.length
      this.audioDatasIndex++
    }
    this.source = this.audioCtx.createBufferSource()
    this.source.buffer = audioBuffer
    this.source.connect(this.audioCtx.destination)
    this.source.start()
    this.source.onended = (event) => {
      this.source.stop()
      if (this.audioDatasIndex < this.audioDatas.length) {
        this.playNext()
      } else {
        this.isPlaying = false
      }
    }

    // //取出第一段
    // const audioData = this.audioDatas.shift()
    // const buffer = this.audioCtx.createBuffer(1, audioData.length, 16000) //22050创建单声道（1），采样率 22050 Hz 的缓冲区。
    // buffer.copyToChannel(audioData, 0) //把解码后的 PCM 数据写入缓冲区

    // this.source = this.audioCtx.createBufferSource() //创建一个 音频源节点，承载一段预先加载/生成的音频数据（buffer），并可以播放它。
    // this.source.buffer = buffer //把之前准备好的音频数据（buffer）赋值给这个源节点。
    // this.source.connect(this.audioCtx.destination) //将音频源连接到 最终输出设备（通常是扬声器或耳机）。

    // //播放完成的回调，继续播放下一段音频
    // this.source.onended = () => {
    //   this.playNext()
    // }

    // this.source.start() //开始播放
  }

  // 确保上下文可用
  async ensureContext() {
    if (!this.audioCtx || this.audioCtx.state === 'closed') {
      await this.init() // 重新创建
    } else if (this.audioCtx.state === 'suspended') {
      await this.audioCtx.resume() // 唤醒
    }
  }
  /**
   * 播放 base64 PCM 音频，传递过来应该是合成的音频
   */
  async play(base64Audio) {
    if (!base64Audio) return
    // 耳机未插入，不做消息队列叠加
    await this.ensureContext()
    await this.checkAndToggleMonitoring()
    if (!this.monitoringConnected) {
      return
    }
    this.worker.postMessage({
      // Worker线程 将 Base64 转为 PCM 音频数据后，会发送 newAudioData 消息。
      command: 'transData',
      data: base64Audio,
      from: 16000,
    })
  }

  stop() {
    // 转成 WAV
    // const wavBlob = this.float32ArrayToWav(this.text, 16000)

    // 创建下载链接
    // const url = URL.createObjectURL(new Blob(this.text))
    // const a = document.createElement('a')
    // a.href = url
    // a.download = 'tts-audio.pcm'
    // a.click()

    if (this.source) {
      this.source.stop()
      this.source = null
    }
    this.audioDatas = []
    this.audioDatasIndex = 0
    this.monitoringConnected = false // 重置状态
    this.isPlaying = false
    if (this.audioCtx) {
      this.audioCtx.close()
      this.audioCtx = null
    }
  }

  // 把Float32Array 数组合并为 WAV 文件
  float32ArrayToWav(floatArrays, sampleRate = 16000) {
    // 合并所有 Float32Array
    const allData = new Float32Array(
      floatArrays.reduce((acc, arr) => acc.concat(Array.from(arr)), [])
    )

    function writeString(view, offset, string) {
      for (let i = 0; i < string.length; i++) {
        view.setUint8(offset + i, string.charCodeAt(i))
      }
    }

    // 转换为 Int16（16位整型）用于 WAV
    const buffer = new ArrayBuffer(44 + allData.length * 2)
    const view = new DataView(buffer)

    // 写入 WAV 头部
    writeString(view, 0, 'RIFF')
    view.setUint32(4, 36 + allData.length * 2, true)
    writeString(view, 8, 'WAVE')
    writeString(view, 12, 'fmt ')
    view.setUint32(16, 16, true)
    view.setUint16(20, 1, true) // format: PCM
    view.setUint16(22, 1, true) // channel count: mono
    view.setUint32(24, sampleRate, true) // sample rate
    view.setUint32(28, sampleRate * 2, true) // byte rate
    view.setUint16(32, 2, true) // block align
    view.setUint16(34, 16, true) // bits per sample
    writeString(view, 36, 'data')
    view.setUint32(40, allData.length * 2, true)

    // 写入音频数据（转换为 Int16）
    for (let i = 0; i < allData.length; i++) {
      const value = Math.max(-1, Math.min(1, allData[i])) // 限幅
      const int16 = Math.round(value * 32767) // 转为 16bit
      view.setInt16(44 + i * 2, int16, true)
    }

    return new Blob([buffer], { type: 'audio/wav' })
  }
}

// ✅ 导出一个实例（单例）
const ttsPlayer = new TtsPlayer()
export default ttsPlayer
